package com.example.llademo.util;

import com.example.llademo.entity.ADSPosition;
import com.example.llademo.entity.LLAPosition;
import com.example.llademo.enums.LlaFileType;
import com.example.llademo.filter.AdsFilterWrapper;
import com.example.llademo.manager.AdsManager;
import com.example.llademo.manager.LlaManager;
import com.example.llademo.model.dto.ExcelReadResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author zhangqi
 * @date 2024/4/1
 * @time 15:17
 * @description
 */
@Component
@Slf4j
public class LlaIOUtil {

    //lla 文件路径
    @Value("${lla.filepath}")
    private String llaFilePath;

    @Value("${lla.results.a0001}")
    private String lla1ResultFilePath;
    @Value("${lla.results.a0002}")
    private String lla2ResultFilePath;

    public String getLlaFilePath() {
        return llaFilePath;
    }

    @Autowired
    private AdsManager adsManager;
    @Autowired
    private LlaManager llaManager;

    //获取路径数据集合
    public List<Resource> getResourcesFromClasspath(String pathPattern) {
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        // 指定classpath下的路径模式，例如："classpath:/files/**"
        try {
            Resource[] resources = resolver.getResources(pathPattern);
            // 将所有匹配的资源转换为列表
            List<Resource> fileList = new ArrayList<>();
            for (Resource resource : resources) {
                if (resource.exists() && resource.isReadable()) {
                    fileList.add(resource);
                }
            }
            return fileList;
        } catch (IOException e) {
            throw new RuntimeException("Failed to retrieve resources from classpath", e);
        }
    }

    //读取lla文件到list
    public List<LLAPosition> readLlaFileByLine(File file) {
        boolean officialRead = false;
        List<LLAPosition> llaPositionList = null;
        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String line;
            while ((line = reader.readLine()) != null) {
                if (line.startsWith("--------------")) {
                    officialRead = true;
                    continue;
                }
                if (officialRead) {
                    if (llaPositionList == null) {
                        llaPositionList = new ArrayList<>();
                    }
//                    log.info("llaFileLine:{}", line);
                    String[] splitLine = line.split("\\s{2,}");
//                    log.info("splitLine size:{}", splitLine.length);
                    if (splitLine.length == 7) {
                        llaPositionList.add(LLAPosition.getLLA(splitLine));
                    }
                }
            }
        } catch (IOException e) {
            log.info("Error reading file:{}", e.getMessage());
        }
        return llaPositionList;
    }

    //获取过滤后的lla position列表
    public List<LLAPosition> readLlaFileByLineWithFilterAds(File file, ExcelReadResult excelReadResult) {
        boolean officialRead = false;
        List<LLAPosition> llaPositionList = null;
        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String line;
            READLINE:
            while ((line = reader.readLine()) != null) {
                if (line.startsWith("--------------")) {
                    officialRead = true;
                    continue;
                }
                if (officialRead) {
                    if (llaPositionList == null) {
                        llaPositionList = new ArrayList<>();
                    }
//                    log.info("llaFileLine:{}", line);
                    String[] splitLine = line.split("\\s{2,}");
//                    log.info("splitLine size:{}", splitLine.length);
                    if (splitLine.length == 7) {
                        LLAPosition llaPosition = LLAPosition.getLLA(splitLine);
                        //1.如果lla时间在飞机起飞前或飞机落地后则略过
                        if (llaPosition.getCaptureTime().before(excelReadResult.getTakeOffTime()) ||
                                llaPosition.getCaptureTime().after(excelReadResult.getLandingTime())) {
                            continue;
                        }
                        //2.获取到与lla position时间相同或相近的飞行器数据，现在是精确到分钟或完全相同时间，todo 以前、后半分钟为范围
                        List<ADSPosition> nearRangeList = adsManager.getNearRangeListByDate(llaPosition.getCaptureTime(), excelReadResult.getAdsList());
                        log.info("nearRangeList:{}", nearRangeList);
                        for (ADSPosition adsPosition : nearRangeList) {
                            boolean isCoverage = AdsFilterWrapper.adsFilter().coverageFilter(adsPosition, llaPosition);
                            if (isCoverage) {
                                llaPositionList.add(llaPosition);
                                continue READLINE;
                            }
                        }

                    }
                }
            }
        } catch (IOException e) {
            log.info("Error reading file:{}", e.getMessage());
        }
        return llaPositionList;
    }

    /**
     * 从resource中读取文件列表
     *
     * @param resourcePath
     * @return
     */
    public List<File> readFilesFromResource(String resourcePath, String suffix) {
        if (!suffix.startsWith(".")) {
            throw new RuntimeException("wrong file suffix, must use '.' at first position eg: .png");
        }
        //1-读取目录文件集合
        List<Resource> resources = getResourcesFromClasspath(resourcePath);
        //2-转为file
        return resources.stream()
                .filter(resource -> Objects.requireNonNull(resource.getFilename()).endsWith(suffix))
                .map(resource -> {
                    try {
                        return resource.getFile();
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                })
                .collect(Collectors.toList());
    }

    //读取lla文件
    public void readLlaFiles() throws IOException {
        //读取路径文件列表
        List<File> fileList = readFilesFromResource(llaFilePath, ".txt");
        //分别读取1号和2号文件
        fileList.forEach(file -> {
            String fileName = file.getName();
            if (fileName.contains(LlaFileType.ONE.getCode())) {
                List<LLAPosition> llaPositionListA0001 = readLlaFileByLine(file);
                log.info(">>>> Read A0001 size:{}", llaPositionListA0001.size());
//                log.info(">>>> Read A0001 size:{} ,\nAnd 1 of list simple:{}", llaPositionListA0001.size(),
//                        llaPositionListA0001.get(new Random().nextInt(llaPositionListA0001.size())));
            }
            if (fileName.contains(LlaFileType.TWO.getCode())) {
                List<LLAPosition> llaPositionListA0002 = readLlaFileByLine(file);
                log.info(">>>> Read A0002 size:{}", llaPositionListA0002.size());
//                log.info(">>>> Read A0002 size:{} ,\nAnd 1 of list simple:{}", llaPositionListA0002.size(),
//                        llaPositionListA0002.get(new Random().nextInt(llaPositionListA0002.size())));
            }
        });
    }

    public Map<String, List<LLAPosition>> readAndGetLlaFiles() throws IOException {
        Map<String, List<LLAPosition>> llaFileMap = new HashMap<>();
        //读取路径文件列表
        List<File> fileList = readFilesFromResource(llaFilePath, ".txt");
        //分别读取1号和2号文件
        fileList.forEach(file -> {
            String fileName = file.getName();
            if (fileName.contains(LlaFileType.ONE.getCode())) {
                List<LLAPosition> llaPositionListA0001 = readLlaFileByLine(file);
                log.info(">>>> Read A0001 size:{}", llaPositionListA0001.size());
                llaFileMap.put(LlaFileType.ONE.getCode(), llaPositionListA0001);
//                log.info(">>>> Read A0001 size:{} ,\nAnd 1 of list simple:{}", llaPositionListA0001.size(),
//                        llaPositionListA0001.get(new Random().nextInt(llaPositionListA0001.size())));
            }
            if (fileName.contains(LlaFileType.TWO.getCode())) {
                List<LLAPosition> llaPositionListA0002 = readLlaFileByLine(file);
                log.info(">>>> Read A0002 size:{}", llaPositionListA0002.size());
                llaFileMap.put(LlaFileType.TWO.getCode(), llaPositionListA0002);
//                log.info(">>>> Read A0002 size:{} ,\nAnd 1 of list simple:{}", llaPositionListA0002.size(),
//                        llaPositionListA0002.get(new Random().nextInt(llaPositionListA0002.size())));
            }
        });
        return llaFileMap;
    }

    //
    public void readAndFilterLlaFiles(ExcelReadResult excelReadResult) throws IOException {
        //读取路径文件列表
        List<File> fileList = readFilesFromResource(llaFilePath, ".txt");
        //分别读取1号和2号文件
        fileList.forEach(file -> {
            String fileName = file.getName();
            if (fileName.contains(LlaFileType.ONE.getCode())) {
                List<LLAPosition> llaPositionListA0001 = readLlaFileByLineWithFilterAds(file, excelReadResult);
                log.info(">>>> Read A0001 size:{}", llaPositionListA0001.size());
                if (llaPositionListA0001.size() > 0) {
                    //写出到txt
                    writeListToFile(llaManager.convertObj2StrList(llaPositionListA0001),lla1ResultFilePath);
                }
//                log.info(">>>> Read A0001 size:{} ,\nAnd 1 of list simple:{}", llaPositionListA0001.size(),
//                        llaPositionListA0001.get(new Random().nextInt(llaPositionListA0001.size())));
            }
            if (fileName.contains(LlaFileType.TWO.getCode())) {
                List<LLAPosition> llaPositionListA0002 = readLlaFileByLineWithFilterAds(file, excelReadResult);
                log.info(">>>> Read A0002 size:{}", llaPositionListA0002.size());
                if (llaPositionListA0002.size() > 0) {
                    //写出到txt
                    writeListToFile(llaManager.convertObj2StrList(llaPositionListA0002),lla2ResultFilePath);
                }
//                log.info(">>>> Read A0002 size:{} ,\nAnd 1 of list simple:{}", llaPositionListA0002.size(),
//                        llaPositionListA0002.get(new Random().nextInt(llaPositionListA0002.size())));
            }
        });
    }

    //写出数据到result
    public void writeListToFile(List<String> dataList,String resultFilePath){
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(resultFilePath))) {
            for (String data : dataList) {
                // 将每条数据写入文件，这里假设列表中的元素都是字符串
                writer.write(data);
                // 添加换行符以便每条记录单独一行
                writer.newLine();
            }
        } catch (IOException e) {
            System.err.println("Error occurred while writing to file: " + e.getMessage());
        }
    }


}
